package com.jackrain.nea.omslocal.Dao;

import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.util.TypeUtils;
import com.jackrain.nea.config.PropertiesConf;
import com.jackrain.nea.omslocal.service.LocalLogService;
import com.jackrain.nea.omslocal.service.SendMqServies;
import com.jackrain.nea.omslocal.util.JsonKeyCheck;
import com.jackrain.nea.omslocal.util.RegexDateUtil;
import com.jackrain.nea.util.ApplicationContextHandle;
import com.jackrain.nea.util.Tools;
import com.jackrain.nea.util.Validator;
import com.jackrain.nea.web.query.QueryEngine;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;

/**
 * Description: 消费保存淘宝退单数据
 * Created with IntelliJ IDEA.
 * User: cs
 * Date: 2017/3/30
 * Time: 16:40
 */
@Component
@Slf4j
public class TaoBaoRefundDao {

    @Autowired
    private RegexDateUtil regexDate;
    @Autowired
    private LocalLogService localLogService;

    private FastDateFormat fastformat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private SendMqServies sendMq;

    /**
     * 保存淘宝退单数据方法
     *
     * @param taobaoorderArr
     * @param topic
     */
    public void refundStart(JSONArray taobaoorderArr, String msgkey, String topic) throws Exception {
        TaoBaoRefundDao taoBaoRefundDao = ApplicationContextHandle.getBean(TaoBaoRefundDao.class);
        PropertiesConf pconf = (PropertiesConf) ApplicationContextHandle.getBean("propertiesConf");

        Long refund_id = 0L;
        int countFaild = 0;
        // 定义接收消费日志信息的 jsonobject
        JSONObject infoObj = new JSONObject();
        List tids = new ArrayList();
        // 获取参数表更新字段
        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);
        // 退单业务么没有明细表,直接新增主表或更新主表
        for (Object obj : taobaoorderArr) {

            JSONObject tempObj = null;
            try {
                // 循环遍历拿到单条退单数据
                JSONObject firstObj = JSONObject.parseObject(obj.toString(), Feature.OrderedField);

                tempObj = firstObj.getJSONObject("jdp_response").getJSONObject("refund_get_response").getJSONObject("refund");
                //tempObj = firstObj.getJSONObject("refund_get_response").getJSONObject("refund");
                // 根据唯一外键判
                refund_id = tempObj.getLong("refund_id");
                // 根据 refund_id 查询数据库,判断该数据是 新增 或是 修改
                String selectSql = "SELECT id FROM T_OMSTAOBAOREFUND WHERE refund_id = ?";
                int id = Tools.getInt(QueryEngine.getInstance().doQueryOne(selectSql, new Object[]{refund_id}), -1);

                if (id < 0) {
                    // 新增数据
                    // 数据不为空 保存数据
                    taoBaoRefundDao.insert(tempObj, topic);
                    // 保存数据到本地日志表
                    localLogService.insertLogDeatail(tempObj, tempObj.getLong("refund_id"), 1, topic, msgkey);
                } else {
                    // 根据查询到的 id 更新主表数据
                    taoBaoRefundDao.update(tempObj, id, topic);
                    // 保存数据到本地日志表
                    localLogService.insertLogDeatail(tempObj, tempObj.getLong("refund_id"), 2, topic, msgkey);
                }

                tids.add(refund_id);

            } catch (Exception e) {

                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                // 逐条将错误信息以消息发送到线上发送到线上
                JSONObject errObj = new JSONObject();
                errObj.put("bus_id", refund_id);
                errObj.put("tablename", pconf.getProperty("ons.tbrefund"));
                errObj.put("topic", topic);
                errObj.put("tag", pconf.getProperty("ons.comp"));
                errObj.put("msgkey", msgkey);
                // 线下消费报错的主机 ip
                errObj.put("client_ip", NetUtils.getLocalAddress());
                // 将错误以流写出
                e.printStackTrace(pw);
                errObj.put("errmsg", sw.toString());
                errObj.put("protime", System.currentTimeMillis());
                errObj.put("code", -1);
                sendMq.sendMqinfoObj(errObj, pconf.getProperty("ons.loginfor.err.topic"), pconf.getProperty("ons.loginfor.err.tag"));
                // 处理异常 ,将出现异常的信息保存到数据库
                localLogService.insertLog(e.getMessage(), tempObj, refund_id, topic, msgkey);
                log.error(e.getMessage() + topic + "=======>" + refund_id);
            }
        }
        // 调用更新线上日志的服务
        infoObj.put("msgkey", msgkey);
        infoObj.put("client_ip", NetUtils.getLocalAddress());
        infoObj.put("topic", topic);
        infoObj.put("countsuccess", (taobaoorderArr.size() - countFaild));
        infoObj.put("protime", System.currentTimeMillis());
        infoObj.put("tids", tids);
        infoObj.put("code", 0);
        infoObj.put("total", taobaoorderArr.size());
        String msgId = sendMq.sendMqinfoObj(infoObj, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
        if("-1".equals(msgId)){
            for(int i = 0; i < 3; i++){
                if(!"-1".equals(msgId)){
                    break;
                }
                //重试回执
                msgId = sendMq.sendMqinfoObj(infoObj, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
            }
        }
        log.debug("taobaorefund消费完成回执 msgId= {}, topic= {}, tag= {}", msgId, pconf.getProperty("ons.loginfor.suf.topic"), pconf.getProperty("ons.loginfor.suf.tag"));
    }

    @Transactional
    public void insert(JSONObject tempObj, String topic) throws Exception {

        Object outId = null;
        // 新增数据
        // 数据不为空 保存数据
        if (!tempObj.isEmpty()) {
            Map map = null;
            map = saveRefund(tempObj);
            outId = map.get("seq");
        } else {
            log.debug("主表数据为空");
        }

        // 在执行完之后需要更改主表的 istrans 字段为 0
        String sql = "update T_OMSTAOBAOREFUND SET istrans = 0 WHERE id = ?";
        QueryEngine.getInstance().executeUpdate(sql, new Object[]{outId});
    }

    @Transactional
    public void update(JSONObject tempObj, int id, String topic) throws Exception {
        // 根据查询到的 id 更新主表数据
        this.updateRefund(tempObj, id);
        // 更新操作之后需要更新 istrans 为0
        String sql = "update T_OMSTAOBAOREFUND SET istrans = 0 WHERE id = ?";
        QueryEngine.getInstance().executeUpdate(sql, new Object[]{id});

    }

    /**
     * 保存退单主表
     *
     * @param jsonObj
     * @return
     * @throws SQLException
     */
    public Map saveRefund(JSONObject jsonObj) throws SQLException, ParseException {

        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);
        jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSTAOBAOREFUND", checkjson.getInsertcolsmap());
        Map map = new HashMap();

        // 将固定需要维护的字段加入 jsonObj,  creatTime, modified , outstatus
        // outstatus 默认值为 1 ,当主表所有明细更新完成,将此状态更改为 2 ;
        // 获取主表的 sequences
        String squnceSql = "select get_wsequences('T_OMSTAOBAOREFUND') as SEQ from dual";
        Long id = TypeUtils.castToLong(QueryEngine.getInstance().doQueryOne(squnceSql));

        Object descobj = jsonObj.get("desc");
        jsonObj.remove("desc");
        jsonObj.put("refunddesc", descobj);
        jsonObj.put("id", id);

        String columnName = "";
        String columnValue = "";
        Set set = jsonObj.keySet();
        Object[] objArr = jsonObj.values().toArray();

        for (Object obj1 : set) {
            columnName = columnName + "," + obj1;
        }
        columnName = columnName.substring(1);

        for (int i = 0; i < objArr.length; i++) {

            if (objArr[i] instanceof String) {
                if (regexDate.regexDate(((String) objArr[i]))) {
                    Date date = fastformat.parse(((String) objArr[i]));
                    objArr[i] = date;
                }
            }
            columnValue = columnValue + ",?";
        }

        columnValue = columnValue.substring(1);
        String sql = "insert into T_OMSTAOBAOREFUND (" + columnName + ") values (" + columnValue + ")";
        int code = QueryEngine.getInstance().executeUpdate(sql, objArr);

        map.put("code", code);
        map.put("seq", id);
        return map;
    }

    /**
     * 更新退单主表
     *
     * @param jsonObj
     * @return
     * @throws SQLException
     */

    public Map updateRefund(JSONObject jsonObj, int id) throws SQLException, ParseException {

        JsonKeyCheck checkjson = (JsonKeyCheck) ApplicationContextHandle.getBean(JsonKeyCheck.class);
        jsonObj = checkjson.checkJsonkeycache(jsonObj, "T_OMSTAOBAOREFUND", checkjson.getUpdatecolsmap());

        Map map = new HashMap();
        // 将固定需要维护的字段加入  modified
        // desc 为关键字
        Object descobj = jsonObj.get("desc");
        jsonObj.remove("desc");
        jsonObj.put("refunddesc", descobj);

        String params = "";
        Set set = jsonObj.keySet();
        Object[] objArr = jsonObj.values().toArray();
        for (Object obj1 : set) {
            Object tempobject = jsonObj.get(obj1);
            params = params + "" + obj1 + " = ?,";
        }
        params = params.substring(0, params.length() - 1);

        for (int i = 0; i < objArr.length; i++) {

            if (Validator.isNull(objArr[i])) {
                objArr[i] = "null";
            }
            if (objArr[i] instanceof String) {
                if (regexDate.regexDate(((String) objArr[i]))) {
                    Date date2 = fastformat.parse(((String) objArr[i]));
                    objArr[i] = date2;
                }
            }
        }

        String sql = "update T_OMSTAOBAOREFUND set " + params + " where id = ?";
        log.debug("======================" + jsonObj.toString());
        int code = QueryEngine.getInstance().executeUpdate(sql, ArrayUtils.add(objArr, id));

        return map;
    }

}
